/* * AngularBeans, CDI-AngularJS bridge * * Copyright (c) 2014, Bessem Hmidi. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * */ /** * @author Bessem Hmidi */ package angularBeans.validation; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import angularBeans.js.cache.StaticJsCache; import angularBeans.util.AngularBeansUtils; import angularBeans.util.ClosureCompiler; import angularBeans.util.CommonUtils; /** * The bean validation processor generates the HTML5 validation attributes from * Bean Validation annotations. * * @author Bessem Hmidi * */ @SuppressWarnings("serial") @ApplicationScoped public class BeanValidationProcessor implements Serializable { private Set<Class> validationAnnotations; @Inject AngularBeansUtils util; private final StringBuffer buffer = new StringBuffer(); public void processBeanValidationParsing(Method method) { String modelName = CommonUtils.obtainFieldNameFromAccessor(method .getName()); Annotation[] scannedAnnotations = method.getAnnotations(); buffer.append("\nif (modelName === '").append(modelName).append("') {"); for (Annotation a : scannedAnnotations) { if (!validationAnnotations.contains(a.annotationType())) { continue; } String name = (a.annotationType().getName()); switch (name) { case "javax.validation.constraints.NotNull": buffer.append("\nentries[e].setAttribute('required', 'true');"); break; case "org.hibernate.validator.constraints.Email": buffer.append("\nentries[e].setAttribute('type', 'email');"); break; case "javax.validation.constraints.Pattern": String regex = ((Pattern) a).regexp(); buffer.append("\nentries[e].setAttribute('ng-pattern', '") .append(regex).append("');"); break; case "javax.validation.constraints.Size": buffer.append("\nentries[e].setAttribute('required', 'true');"); Size sizeConstraint = (Size) a; int maxLength = sizeConstraint.max(); int minLength = sizeConstraint.min(); if (minLength < 0) { throw new IllegalArgumentException("The min parameter cannot be negative."); } if (maxLength < 0) { throw new IllegalArgumentException("The max parameter cannot be negative."); } if (minLength > 0) { buffer.append("\nentries[e].setAttribute('ng-minlength', '") .append(minLength).append("');"); } if (maxLength < Integer.MAX_VALUE) { buffer.append("\nentries[e].setAttribute('ng-maxlength', '") .append(maxLength).append("');"); } break; case "javax.validation.constraints.DecimalMin": String dMin = ((DecimalMin) a).value(); buffer.append("\nentries[e].setAttribute('min', '") .append(dMin).append("');"); break; case "javax.validation.constraints.DecimalMax": String dMax = ((DecimalMax) a).value(); buffer.append("\nentries[e].setAttribute('max', '") .append(dMax).append("');"); break; case "javax.validation.constraints.Min": long min = ((Min) a).value(); buffer.append("\nentries[e].setAttribute('min', '").append(min) .append("');"); break; case "javax.validation.constraints.Max": long max = ((Max) a).value(); buffer.append("\nentries[e].setAttribute('max', '").append(max) .append("');"); break; default: break; } } buffer.append("\n}"); } @PostConstruct public void init() { validationAnnotations = new HashSet<>(); validationAnnotations.addAll(Arrays.asList(NotNull.class, Size.class, Pattern.class, DecimalMin.class, DecimalMax.class, Min.class, Max.class)); } public void build() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("app"); stringBuilder.append(".directive('beanValidate', function($compile) {"); stringBuilder.append("\nreturn {"); stringBuilder.append("\ncompile : function(tElem, attrs) {"); stringBuilder .append("\nreturn function(scope, elem, attrs, compile) {"); stringBuilder.append("\nvar getAllInputModel = function(attribute) {"); stringBuilder.append("\nvar matchingElements = [];"); stringBuilder .append("\nvar allElements = document.getElementsByTagName('input');"); stringBuilder .append("\nfor (var i = 0, n = allElements.length; i < n; i++) {"); stringBuilder.append("\nif (allElements[i].getAttribute(attribute)) {"); stringBuilder.append("\nmatchingElements.push(allElements[i]);"); stringBuilder.append("\n}}"); stringBuilder.append("\nreturn matchingElements;}"); stringBuilder.append("\nvar entries = (getAllInputModel('name'));"); stringBuilder.append("\nfor (e in entries) {"); stringBuilder .append("\nvar modelName = (entries[e].getAttribute('name'));"); stringBuilder.append(buffer); stringBuilder.append("\n};"); stringBuilder .append("\nvar old = \"<!-- validation -->\" + elem.html();"); stringBuilder.append("\nelem.html('');"); stringBuilder.append("\nelem.append($compile(old)(scope));"); stringBuilder.append("\n;};}};});"); StaticJsCache.VALIDATION_SCRIPT.append(new ClosureCompiler().getCompressedJavaScript(stringBuilder.toString())); } }